using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Nullables;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Support;
using Sedna.Core.Tiles.Contents;
using Sedna.Domain;
using Sedna.Domain.Enum;

namespace Sedna.Core.Controls
{
    [ValidationProperty("TotalMilliseconds")]
    public class TimePicker : BaseControl, IContent, IConfigurationAware, IClientScriptingControl, IControlDataLoadAware
    {
        private System.Web.UI.WebControls.DropDownList hoursList = new System.Web.UI.WebControls.DropDownList();
        private System.Web.UI.WebControls.DropDownList minutesList = new System.Web.UI.WebControls.DropDownList();
        private System.Web.UI.WebControls.DropDownList secondsList = new System.Web.UI.WebControls.DropDownList();
        private System.Web.UI.WebControls.DropDownList ampmList = new System.Web.UI.WebControls.DropDownList();

        private Time time;
        

        # region Constructors

        public TimePicker()
            : base()
        {
        }

        public TimePicker(IConfiguration configuration)
            : base(configuration)
        {
            BuildControlFromConfiguration();
        }

        # endregion

        # region Properties

        public new ITimePickerConfiguration Configuration
        {
            get { return configuration as ITimePickerConfiguration; }
            set { configuration = value; }
        }

        public override bool Enabled
        {
            get { return base.Enabled; }
            set
            {
                base.Enabled = value;
                
                hoursList.Enabled = value;
                minutesList.Enabled = value;
                secondsList.Enabled = value;
                ampmList.Enabled = value;                
            }
        }

        public override bool Visible
        {
            get { return base.Visible; }
            set
            {
                base.Visible = value;

                hoursList.Visible = Configuration.ShowHours && value;
                minutesList.Visible = Configuration.ShowMinutes && value;
                secondsList.Visible = Configuration.ShowSeconds && value;
                ampmList.Visible = !Configuration.Use24HourTimeScale && value;  
            }
        }
        
        public String TotalMilliseconds
        {
            get
            { 
                Time t = Value; 
                return (t != null) ? t.TotalMilliseconds.ToString(CultureInfo.InvariantCulture) : String.Empty;
            }
        }
        
        public Time Value
        {
            get
            {
                if (Configuration.AllowEmptyTime &&
                    (!hoursList.Visible || hoursList.SelectedIndex == 0) &&
                    (!minutesList.Visible || minutesList.SelectedIndex == 0) &&
                    (!secondsList.Visible || secondsList.SelectedIndex == 0))
                {
                    return null;
                }

                if (time == null)
                    time = new Time();
                                               
                int hours = int.Parse(hoursList.SelectedValue);

                if (!Configuration.ShowHours || hours == -1)
                {
                    hours = time.Hours;
                    
                    int scaledHours = hours;

                    if (!Configuration.Use24HourTimeScale)
                    {
                        if (scaledHours >= 12)
                        {
                            ampmList.SelectedValue = "pm";

                            if (scaledHours > 12 && scaledHours < 24)
                                scaledHours -= 12;
                            else 
                                if (scaledHours == 24)
                                {
                                    ampmList.SelectedValue = "am";
                                    scaledHours = 12;
                                }
                        }
                        else // from 0 to 11
                        {
                            ampmList.SelectedValue = "am";
                            
                            if (scaledHours == 0)
                                scaledHours = 12;                                                        
                        }
                    }

                    hoursList.SelectedValue = scaledHours.ToString();
                }
                else
                    if (!Configuration.Use24HourTimeScale && ampmList.SelectedValue.Equals("pm") && hours < 12)
                    {
                        hours += 12;
                    }

                int minutes = int.Parse(minutesList.SelectedValue);

                if (!Configuration.ShowMinutes || minutes == -1)
                {
                    minutes = 0;
                    minutesList.SelectedValue = minutes.ToString();
                }

                int seconds = int.Parse(secondsList.SelectedValue);

                if (!Configuration.ShowSeconds || seconds == -1)
                {
                    seconds = 0;
                    secondsList.SelectedValue = seconds.ToString();
                }
               
                time = new Time(hours, minutes, seconds);
                
                return time;
            }
            
            set
            {
                if (value == null && !Configuration.AllowEmptyTime)
                    throw new ArgumentException("This TimePicker doesn't support null time");
                
                time = value; 

                if (time == null)
                {
                    hoursList.SelectedIndex = 0;
                    minutesList.SelectedIndex = 0;
                    secondsList.SelectedIndex = 0;
                    
                    return;
                }                                

                hoursList.SelectedValue = time.ScaleHours((Configuration.Use24HourTimeScale) ? TimeScale.Hour24 : TimeScale.Hour12).ToString();
                minutesList.SelectedValue = time.Minutes.ToString();
                secondsList.SelectedValue = time.Seconds.ToString();

                if (!Configuration.Use24HourTimeScale)
                {
                    ampmList.SelectedValue = (time.IsAnteMeridiem) ? "am" : "pm";
                }
            }
        }
        
        public String Text
        {
            get
            {
                Time t = Value;

                return (t == null) ? "" : t.ToShortFormat();
            }
            set
            {
                Value = (String.IsNullOrEmpty(value)) ? null : Time.Parse(value);
            }
        }
        
        # endregion        

        private void BuildControlFromConfiguration()
        {
            base.Build();

            if (Configuration == null)
                return;


            # region Filling controls

            if (Configuration.AllowEmptyTime)
            {
                //ampmList.Items.Add(new ListItem("", "-1"));
                hoursList.Items.Add(new ListItem("", "-1"));
                minutesList.Items.Add(new ListItem("", "-1"));
                secondsList.Items.Add(new ListItem("", "-1"));
            }

            ampmList.Items.Add(new ListItem((Configuration.UseCaps) ? "A.M." : "a.m.", "am"));
            ampmList.Items.Add(new ListItem((Configuration.UseCaps) ? "P.M." : "p.m.", "pm"));

            if (Configuration.Use24HourTimeScale)
            {
                for (int i = 0; i < 24; i++)
                {
                    hoursList.Items.Add(new ListItem((!String.IsNullOrEmpty(Configuration.PadHourByChar)) ? i.ToString().PadLeft(2, Configuration.PadHourByChar[0]) : i.ToString(), i.ToString()));                    
                }
            }
            else
            {
                for (int i = 1; i <= 12; i++)
                {
                    hoursList.Items.Add(new ListItem((!String.IsNullOrEmpty(Configuration.PadHourByChar)) ? i.ToString().PadLeft(2, Configuration.PadHourByChar[0]) : i.ToString(), i.ToString()));
                }
            }

            for (int i = 0; i < 60; i++)
            {
                minutesList.Items.Add(new ListItem(i.ToString().PadLeft(2, '0'), i.ToString()));
                secondsList.Items.Add(new ListItem(i.ToString().PadLeft(2, '0'), i.ToString()));
            }

            # endregion


            hoursList.Visible = Configuration.ShowHours;
            minutesList.Visible = Configuration.ShowMinutes;
            secondsList.Visible = Configuration.ShowSeconds;
            ampmList.Visible = !Configuration.Use24HourTimeScale;

            hoursList.Width = Configuration.Width;
            hoursList.Height = Configuration.Height;

            minutesList.Width = Configuration.Width;
            minutesList.Height = Configuration.Height;

            secondsList.Width = Configuration.Width;
            secondsList.Height = Configuration.Height;

            ampmList.Width = Configuration.Width;
            ampmList.Height = Configuration.Height;

            hoursList.CssClass = "inputsmall";
            minutesList.CssClass = "inputsmall";
            secondsList.CssClass = "inputsmall";
            ampmList.CssClass = "inputsmall";

            Controls.Add(hoursList);

            if (Configuration.UseTimePartSeparator && Configuration.ShowHours)
                Controls.Add(CreateTimeSeparator(Configuration.UseCaps ? "H&nbsp;" : "h&nbsp;"));

            //if (Configuration.ShowHours && Configuration.ShowMinutes)
            //{
            //    Controls.Add(CreateTimeSeparator(null));
            //}

            Controls.Add(minutesList);

            if (Configuration.UseTimePartSeparator && Configuration.ShowMinutes)
                Controls.Add(CreateTimeSeparator(Configuration.UseCaps ? "M&nbsp;" : "m&nbsp;"));


            //if (Configuration.ShowMinutes && Configuration.ShowSeconds)
            //{
            //    Controls.Add(CreateTimeSeparator(null));                
            //}

            Controls.Add(secondsList);

            if (Configuration.UseTimePartSeparator && Configuration.ShowSeconds)
                Controls.Add(CreateTimeSeparator(Configuration.UseCaps ? "S&nbsp;" : "s&nbsp;"));

            Controls.Add(ampmList);
        }

        private Control CreateTimeSeparator(string separator)
        {
            Literal control = new Literal();

            if (separator == null)
                // control.Text = "<table> <tr> <td align=\"center\" valign=\"middle\"> : </td> </tr> </table>";
                // control.Text = "<div> : </div>";
                control.Text = "&nbsp;:&nbsp;";
            else
                control.Text = separator;

            return control;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (Configuration.VisibleBindPath != null)
                Visible = true; // To reach the OnPreRender method and analyze visibility in the Bind method
        }

        protected override void Bind()
        {
            Visible = Configuration.Visible;

            binder.Bind(new String[] { "Enabled", "Visible", "Value", "Text" });

            Enabled = Enabled && Configuration.IsEnabledForPrincipal();
            Visible = Visible && Configuration.IsVisibleForPrincipal();
        }

        protected override void Unbind()
        {
            binder.Unbind("Value", configuration.DataParser);
            binder.Unbind("Text");
            
            binder.Unbind(new String[] { "Enabled", "Visible"});
        }
    }
}
